#include <iomanip>
#include <iostream>
using namespace std;

class Base {
 public:
  Base(int a = 0) : m_a(a) {}
  int get_a() const { return m_a; }
  virtual void func() const {}

 protected:
  int m_a;
};

class Derived : public Base {
 public:
  Derived(int a = 0, int b = 0) : Base(a), m_b(b) {}
  int get_b() const { return m_b; }

 private:
  int m_b;
};

void test1() {
  //情况①
  Derived *pd1 = new Derived(35, 78);
  Base *pb1 = dynamic_cast<Derived *>(pd1);
  cout << "pd1 = " << pd1 << ", pb1 = " << pb1 << endl;
  cout << pb1->get_a() << endl;
  pb1->func();

  //情况②
  int n = 100;
  Derived *pd2 = reinterpret_cast<Derived *>(&n);
  Base *pb2 = dynamic_cast<Base *>(pd2);
  cout << "pd2 = " << pd2 << ", pb2 = " << pb2 << endl;
  cout << pb2->get_a() << endl;  //输出一个垃圾值
  pb2->func();                   //内存错误
}

// 测试向下转型
// 类的虚函数表的前一项即RTTI信息中是否有要转型的相关信息，有则成功，否则失败；
class A {
 public:
  virtual void func() const { cout << "Class A" << endl; }

 private:
  int m_a;
};

class B : public A {
 public:
  virtual void func() const { cout << "Class B" << endl; }

 private:
  int m_b;
};

class C : public B {
 public:
  virtual void func() const { cout << "Class C" << endl; }

 private:
  int m_c;
};

class D : public C {
 public:
  virtual void func() const { cout << "Class D" << endl; }

 private:
  int m_d;
};

void test2() {
  A *pa = new A();
  B *pb;
  C *pc;

  //情况①
  pb = dynamic_cast<B *>(pa);  //向下转型失败
  if (pb == NULL) {
    cout << "Downcasting failed: A* to B*" << endl;
  } else {
    cout << "Downcasting successfully: A* to B*" << endl;
    pb->func();
  }
  pc = dynamic_cast<C *>(pa);  //向下转型失败
  if (pc == NULL) {
    cout << "Downcasting failed: A* to C*" << endl;
  } else {
    cout << "Downcasting successfully: A* to C*" << endl;
    pc->func();
  }

  cout << "-------------------------" << endl;

  //情况②
  pa = new D();                //向上转型都是允许的
  pb = dynamic_cast<B *>(pa);  //向下转型成功
  if (pb == NULL) {
    cout << "Downcasting failed: A* to B*" << endl;
  } else {
    cout << "Downcasting successfully: A* to B*" << endl;
    pb->func();
  }
  pc = dynamic_cast<C *>(pa);  //向下转型成功
  if (pc == NULL) {
    cout << "Downcasting failed: A* to C*" << endl;
  } else {
    cout << "Downcasting successfully: A* to C*" << endl;
    pc->func();
  }
}
int main() {
  test1();
  test2();
  return 0;
}